package com.lhkj.ct.framework.shiro.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lhkj.ct.base.enums.ReturnStatus;
import com.lhkj.ct.base.model.ro.ActionResult;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * <p>
 *      拦截器
 * </p>
 */
public class MyFormAuthenticationFilter extends FormAuthenticationFilter {

    protected final Logger log = LoggerFactory.getLogger(MyFormAuthenticationFilter.class);

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        Subject subject = getSubject(request, response);
        boolean login = subject.isAuthenticated() && subject.getPrincipal() != null;
        boolean isLoginRequest = this.isLoginRequest(request, response);
        boolean isPermissive = super.isPermissive(mappedValue);
        return login || (!isLoginRequest && isPermissive);
    }

    /**
     * TODO 在用户尝试访问受保护的资源但未通过身份验证时被调用，可以在该方法中实现自定义的行为逻辑。
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        Subject subject = getSubject(request, response);
        // 判断是不是登录页面
        if (isLoginRequest(request, response)) {
            // 判断是否http请求，并且是post方法
            if (super.isLoginSubmission(request, response)) {
                if (log.isTraceEnabled()) {
                    log.trace("Login submission detected.  Attempting to execute login.");
                }
                AuthenticationToken token = createToken(request, response);
                if (token == null) {
                    String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken " +
                            "must be created in order to execute a login attempt.";
                    throw new IllegalStateException(msg);
                }
                try {
                    subject.login(token);
                    return this.onLoginSuccess(token, subject, request, response);
                } catch (AuthenticationException e) {
                    return onLoginFailure(token, e, request, response);
                }
            } else {
                if (log.isTraceEnabled()) {
                    log.trace("Login page view.");
                }
                //allow them to see the login page ;)
                return true;
            }
        } else {
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            HttpServletResponse httpServletResponse = (HttpServletResponse) response;
//            // 判断是否options请求
            if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
                httpServletResponse.setStatus(HttpStatus.OK.value());
                return true;
            }
            if (log.isTraceEnabled()) {
                log.trace("Attempting to access a path which requires authentication.  Forwarding to the " +
                        "Authentication url [" + getLoginUrl() + "]");
            }
            // 判断是否ajax、xhr、axios请求
            boolean isHttpRequest = (null != httpServletRequest.getHeader("X-Requested-With")) || ((HttpServletRequest) request).getRequestURI().contains("api");
            // 如果是异步请求类型，重定向正常但是页面是无法刷新的
            if (isHttpRequest) {
                httpServletResponse.setHeader("Access-Control-Allow-Origin", httpServletRequest.getHeader("Origin"));
                httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
                httpServletResponse.setContentType("application/json; charset=utf-8");
                httpServletResponse.setCharacterEncoding("UTF-8");
                PrintWriter out = httpServletResponse.getWriter();
                // 有登录的情况下，则是无权限
                if (subject.isAuthenticated()) {
                    out.write(new ObjectMapper().writeValueAsString(ActionResult.fail(ReturnStatus.SC_UNAUTHORIZED)));
                }else{
                    out.write(new ObjectMapper().writeValueAsString(ActionResult.fail(ReturnStatus.NO_LOGIN)));
                }
                out.flush();
                out.close();
            } else {
                saveRequest(request);
                PrintWriter out = httpServletResponse.getWriter();
                // 有登录的情况下，则是无权限
                if (subject.isAuthenticated()) {
                    out.write(new ObjectMapper().writeValueAsString(ActionResult.fail(ReturnStatus.SC_UNAUTHORIZED)));
                }else{
                    out.write(new ObjectMapper().writeValueAsString(ActionResult.fail(ReturnStatus.NO_LOGIN)));
                }
                out.flush();
                out.close();
//                saveRequestAndRedirectToLogin(request, response);
            }
            return false;
        }
    }

//    @Override
//    protected boolean isLoginRequest(ServletRequest request, ServletResponse response) {
//        return pathsMatch("/login/in", request);
//    }

//    /**
//     * 登录成功
//     */
//    @Override
//    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
//        if (!StringUtils.isEmpty(getSuccessUrl())) {
//            // 如果当前session为null,则返回null,而不是创建一个新的session
//            Session session = subject.getSession(false);
//            if (session != null) {
//                session.removeAttribute("shiroSavedRequest");
//            }
//        }
//        this.issueSuccessRedirect(request, response);
//        return true;
//    }

//    /**
//     * 执行登录成功跳转
//     */
//    @Override
//    protected void issueSuccessRedirect(ServletRequest request, ServletResponse response) throws Exception {
//        System.err.println("执行登录跳转：" + getSuccessUrl());
//        WebUtils.issueRedirect(request, response, getSuccessUrl(), null, true);
//    }

//    /**
//     * 跳转登录页
//     */
//    @Override
//    protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
//        HttpServletRequest req = (HttpServletRequest) request;
//        String loginUrl = getLoginUrl();
//        String url = req.getRequestURI();
//        if (url.contains("/h5/")) {
//            loginUrl = "/unauth";
//        }
//        WebUtils.issueRedirect(request, response, loginUrl);
//    }
}
